package org.bluedream.core.utils.thymeleaf;

import com.alibaba.fastjson.JSONObject;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.bluedream.comm.utils.EmptyUtil;
import org.thymeleaf.IEngineConfiguration;
import org.thymeleaf.context.ITemplateContext;
import org.thymeleaf.model.IModel;
import org.thymeleaf.model.IModelFactory;
import org.thymeleaf.model.IProcessableElementTag;
import org.thymeleaf.standard.expression.IStandardExpression;
import org.thymeleaf.standard.expression.IStandardExpressionParser;
import org.thymeleaf.standard.expression.StandardExpressions;
import java.io.Serializable;
import java.util.*;

/**
 * @ClassName ThymeleafTag
 * @Description TODO
 * @Author foxsand
 * @Data 2021-08-18 15:34
 * @Version
 */

@NoArgsConstructor
public class ThymeleafTag implements Serializable {
    private static final long serialVersionUID = -3379203686015191740L;
    @Setter
    @Getter
    private String typeDict;
    private List<String> tagAttributeNames = new ArrayList<>();
    private IModelFactory factory;

    public ThymeleafTag(ITemplateContext context) {
        this.factory = createFactory(context);
    }

    private void setTag(String type){
        this.tagAttributeNames.add("url");//请求地址
        this.tagAttributeNames.add("title");//请求地址
        this.tagAttributeNames.add("id");//表单绑定id
        this.tagAttributeNames.add("submitValue");  //提交值
        if (type.equals("zTree")){
            this.tagAttributeNames.add("submitAttributeName");//提交值属性名称
            this.tagAttributeNames.add("isShowCode");//是否显示编码
            this.tagAttributeNames.add("canSelectRoot");//根节点是否可选
            this.tagAttributeNames.add("canSelectParent");//父节点是否可选
            this.tagAttributeNames.add("excludeCode" );//排除节点 元素name的值
            this.tagAttributeNames.add("isExpandAll");//是否展示节点，默认false
            this.tagAttributeNames.add("objectType");//组织 - 关系表，更新组织信息,type
            this.tagAttributeNames.add("objectUrl");//组织 - 关系表，更新组织信息,请求地址
            this.tagAttributeNames.add("objectEl");//组织 - 关系表，更新组织信息,更新目标元素ID前缀
        }
    }

    private IModelFactory createFactory(ITemplateContext context){
        return context.getModelFactory();
    }

    public IModel getLoginOrgTreeDataTag(ITemplateContext context, IProcessableElementTag tag , String type){
//        IModelFactory factory = createFactory(context);
        IModel rootModel = this.factory.createModel();       //页面根节点
        IModel submitModel = this.factory.createModel();     //form表单中实际提交的input标签
        IModel showInputModel = this.factory.createModel();  //form中回显的input名称

        //前端
        String activeId = tag.getAttribute("id").getValue(); //id
        String activeName = tag.getAttribute("name").getValue();    //name
        String submitValue = getExpressionValue(context , tag.getAttribute("submitValue").getValue()); //提交值
        String showValue = getExpressionValue(context , tag.getAttribute("showValue").getValue()); //回显内容

        //返回给前端的 JSON对象
        JSONObject optionJSON = getJSONStr(context , tag , type);

        //隐藏input
        String inputId = activeId + "Code";
        submitModel.add(this.factory.createOpenElementTag(String.format("input type='hidden' id='%s' name='%s' value='%s'" , inputId , activeName , submitValue)));
        rootModel.addModel(submitModel);

        // form中回显input
        inputId = activeId + "Name";
        String classStyle = "layui-input " + type + "Btn";
        showInputModel.add(this.factory.createOpenElementTag(String.format("input type='text' id='%s' value='%s' class='%s' lay-verify='required' placeholder='登录组织' readonly data='%s'/" , inputId , showValue , classStyle , optionJSON)));
        rootModel.addModel(showInputModel);

        return rootModel;
    }

    public IModel getModelTag(ITemplateContext context, IProcessableElementTag tag , String type){
//        IModelFactory factory = createFactory(context);
        IModel rootModel = this.factory.createModel();       //页面根节点
        IModel submitModel = this.factory.createModel();     //form表单中实际提交的input标签
        IModel showInputModel = this.factory.createModel();  //form中回显的input名称

        //前端
        String activeId = tag.getAttribute("id").getValue(); //id
        String activeName = tag.getAttribute("name").getValue();    //name
        String submitValue = getExpressionValue(context , tag.getAttribute("submitValue").getValue()); //提交值
        String showValue = getExpressionValue(context , tag.getAttribute("showValue").getValue()); //回显内容

        //返回给前端的 JSON对象
        JSONObject optionJSON = getJSONStr(context , tag , type);

        //定义class属性
        String classStyle = EmptyUtil.isEmpty(tag.getAttribute("classStyle"))?"blue-tree-line layui-input-block":"blue-tree-line " + tag.getAttribute("classStyle").getValue();
        // todo：创建闭合标签：createOpenElementTag 创建开始标签，createCloseElementTag 创建结束标签
        // todo：非闭合标签：仅createOpenElementTag即可
        rootModel.add(this.factory.createOpenElementTag(String.format("div class='%s'" , classStyle)));   //div 开始标签

        //隐藏input
        String inputId = activeId + "Code";
        submitModel.add(this.factory.createOpenElementTag(String.format("input type='hidden' id='%s' name='%s' value='%s'" , inputId , activeName , submitValue)));
        rootModel.addModel(submitModel);

        // form中回显input
        classStyle = "layui-input " + type + "Btn";
        inputId = activeId + "Name";
        showInputModel.add(this.factory.createOpenElementTag(String.format("input class='%s' type='text'  id='%s' value='%s' autocomplete='off' readonly data='%s'/" , classStyle , inputId , showValue , optionJSON)));
        rootModel.addModel(showInputModel);

        // 搜索图标div
//        final IModel btnDivModel = factory.createModel();
//        classStyle = "layui-btn";
//        btnDivModel.add(factory.createOpenElementTag(String.format("div class='%s'" , classStyle)));
        // 搜索图标 内部button
        final IModel iconModel = factory.createModel();
        classStyle = "blue-tree-icon layui-icon layui-icon-search " + type + "Btn";
        inputId = activeId + "Btn";
        iconModel.add(this.factory.createOpenElementTag(String.format("label class='%s' id='%s'  data='%s' " , classStyle , inputId , optionJSON)));
        iconModel.add(this.factory.createCloseElementTag("label"));

        rootModel.addModel(iconModel);

        rootModel.add(this.factory.createCloseElementTag("div"));                                   //div 闭合标签
        return rootModel;
    }

    private JSONObject getJSONStr(ITemplateContext context, IProcessableElementTag tag , String type){
        this.setTag(type);
        StringBuffer sb = new StringBuffer();
        sb.append("{");
        for (int i = 0; i < this.tagAttributeNames.size(); i++) {
            String key = this.tagAttributeNames.get(i);
            String value = "";
            if (EmptyUtil.isNoEmpty(tag.getAttribute(key))){
                value = tag.getAttribute(key).getValue();
            }else if (key.equals("submitAttributeName") && EmptyUtil.isEmpty(tag.getAttribute(key))){
                value = "id";
            }else {
                continue;
            }
            if (type.equals("zTree")){
                if (key.equals("canSelectRoot") || key.equals("canSelectParent")){
                    sb.append(key + ":" + value);
                }else if (key.equals("id")){
                    sb.append("echoId:'" + value + "'");
                }else {
                    sb.append(key + ":'" + value + "'");
                }
            }else {
                sb.append(key + ":'" + value + "'");
            }
            if (i != this.tagAttributeNames.size() - 1){
                sb.append(",");
            }
        }

        sb.append("}");
        return JSONObject.parseObject(sb.toString());
    }

    /**
     * 解析Thymeleaf标准表达式
     * @param context           上下文
     * @param expressionString  Thymeleaf标准表达式 Value
     * @return
     */
    private String getExpressionValue(ITemplateContext context , String expressionString){
        // todo：使用IStandardExpression 解析Thymeleaf标准表达式，try...catch不抛异常，catch中 赋予空字符串
        // 引擎配置
        IEngineConfiguration configuration = context.getConfiguration();
        // 获取 Thymeleaf标准表达式解析器
        IStandardExpressionParser parser = StandardExpressions.getExpressionParser(configuration);
        // 用于解析Thymeleaf标准表达式
        IStandardExpression expression = parser.parseExpression(context , expressionString);
        try {
            return (String) expression.execute(context);
        }catch (Exception e){
            return "";
        }
    }

}
